/*
 * Copyright (c) JoinQuant Development Team
 * Author: Huayong Kuang <kuanghuayong@joinquant.com>
 */

#include <iostream>
#include "datetime.h"

DateTime::DateTime(int year, int month, int day,
                   int hour, int minute, int second, int microsecond)
    : year(year), month(month), day(day),
      hour(hour), minute(minute), second(second), microsecond(microsecond) {
}

DateTime::DateTime(struct timeval tv) : m_tv(tv) {
    localtime_r(&m_tv.tv_sec, &m_tm);
    setValues();
}

DateTime::DateTime(struct tm time) : m_tm(time) {
    m_tv.tv_sec = mktime(&m_tm);
    m_tv.tv_usec = 0;
    setValues();
}

void DateTime::setValues() {
    year = m_tm.tm_year;
    month = m_tm.tm_mon;
    day = m_tm.tm_mday;
    hour = m_tm.tm_hour;
    minute = m_tm.tm_min;
    second = m_tm.tm_sec;
    microsecond = m_tv.tv_usec;
}

static DateTime DateTime::now() {
    DateTime dt;
    gettimeofday(&dt.m_tv, NULL);
    dt.m_tm = localtime(&m_tv.tv_sec);
    dt.setValues();
    return dt;
}

static DateTime DateTime::fromtimestamp(int64_t usec) {
    DateTime dt;
    dt.m_tv.tv_sec = usec / 1000;
    dt.m_tv.tv_usec = usec % 1000;
    dt.m_tm = localtime(&dt.m_tv.tv_sec);
    dt.setValues();
    return dt;
}

static DateTime DateTime::fromstr(const string str, const string format, bool hasUsec) {
    // 存储除毫秒以外的部分
    char dt_str[30];
    // 存储毫秒部分，目前仅支持毫秒在尾部的情况，如 09:59:55.590
    char dt_m_str[10];
    if (hasUsec) {  // 包含微秒
        int n_pos = str.find(".")
        if (n_pos == string::npos) {  // 没有在时间字符串中找到点号
            dt_str = str.c_str();
            dt_m_str = { '\0' }
        } else {
            dt_str = str.substr(0, n_pos).c_str();
            dt_m_str = str.substr(n_pos + 1, 6).c_str();
        }
    } else {
        dt_str = str.c_str();
        dt_m_str = { '\0' }
    }
    dt = DateTime();
    strptime(&dt_str, &format.c_str(), dt.m_tm);
    m_tv.tv_sec = mktime(&tm)
    if (strlen(dt_m_str) != 0) {
        char buf[10];
        sprintf(buf, "%06s", dt_m_str);
        m_tv.tv_usec = atoi(buf);
    } else {
        m_tv.tv_usec = 0;
    }
    dt.setValues();
    return dt;
}


string DateTime::tostr(const string format, int usecMode) {
    char buf[20], buf2[30];
    strftime(buf, sizeof(buf), format.c_str(), localtime(&m_tv.tv_sec));
    if (usecMode == 1) {  // 把微秒处理成毫秒放到字符串尾部
        sprintf(buf2, "%s.%03d", buf, m_tv.tv_usec);
    } else if (usecMode == 2) {  // 直接把微秒保留到尾部
        sprintf(buf2, "%s.%06d", buf, m_tv.tv_usec);
    } else {
        strcpy(buf2, buf);
    }
}
